﻿namespace MicroCloud.Identity
{
    /// <summary>
    /// 业务实现：身份认证模块
    /// </summary>
    public partial class IdentityService
    {
        #region "属性"
        #region "获取 用户组织机构信息查询数据集"
        /// <summary>
        /// 获取 组织机构信息查询数据集
        /// </summary>
        public IQueryable<UserOrganization> UserOrganizations => UserOrganizationRepository.QueryAsNoTracking();
        #endregion
        #region "获取 用户组织机构仓储"
        /// <summary>
        /// 获取 用户组织机构仓储
        /// </summary>
        protected IUserOrganizationStore<User> UserOrganizationStore => _provider.GetService<IUserOrganizationStore<User>>();
        #endregion

        #endregion

        #region "方法"
        #region "检查用户组织机构信息信息是否存在"
        /// <summary>
        /// 检查用户组织机构信息信息是否存在
        /// </summary>
        /// <param name="predicate">检查谓语表达式</param>
        /// <param name="id">用户组织机构信息编号</param>
        /// <returns>用户组织机构信息是否存在</returns>
        public async Task<bool> CheckUserOrganizationExists(Expression<Func<UserOrganization, bool>> predicate, long id = default)
        {
            return await UserOrganizationRepository.CheckExistsAsync(predicate, id);
        }
        #endregion
        #region "更新用户组织机构信息"
        /// <summary>
        /// 更新用户组织机构信息
        /// </summary>
        /// <param name="dtos">用户组织机构信息集合</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> UpdateUserOrganizations(params UserOrganizationInputDto[] dtos)
        {
            Check.Validate<UserOrganizationInputDto, long>(dtos, nameof(dtos));

            var userIds = new List<string>();
            OperationResult result = await UserOrganizationRepository.UpdateAsync(dtos,
                (dto, entity) =>
                {
                    string userId = UserOrganizationRepository.QueryAsNoTracking(m => m.UserId == entity.UserId).Select(m => m.User.Id.ToString()).FirstOrDefault();
                    userIds.AddIfNotNull(userId);
                    return Task.FromResult(0);
                });
            if (result.Succeeded && userIds.Count > 0)
            {
                var eventData = new OnlineUserCacheRemoveEventData() { UserIds = userIds.ToArray() };
                await EventBus.PublishAsync(eventData);
            }
            return result;
        }
        #endregion
        #region "删除用户组织机构信息"
        /// <summary>
        /// 删除用户组织机构信息
        /// </summary>
        /// <param name="ids">用户组织机构信息编号</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> DeleteUserOrganizations(params long[] ids)
        {
            var userIds = new List<string>();
            OperationResult result = await UserOrganizationRepository.DeleteAsync(ids,
                (entity) =>
                {
                    string userId = UserOrganizationRepository.QueryAsNoTracking(m => m.UserId == entity.UserId).Select(m => m.User.Id.ToString()).FirstOrDefault();
                    userIds.AddIfNotNull(userId);
                    return Task.FromResult(0);
                });
            if (result.Succeeded && userIds.Count > 0)
            {
                var eventData = new OnlineUserCacheRemoveEventData() { UserIds = userIds.ToArray() };
                await EventBus.PublishAsync(eventData);
            }

            return result;
        }
        #endregion
        #region "设置用户的组织机构"
        /// <summary>
        /// 设置用户的组织机构
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <param name="dtos">用户组织机构DTO集合</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> SetUserOrganizations(long userId, params UserOrganizationDto[] dtos)
        {
            User user = await UserManager.FindByIdAsync(userId.ToString());
            if (user == null)
            {
                return OperationResult.Error(I18N.T("用户 {0} 不存在", userId));
            }
            var existOrganizations = UserOrganizations.Where(m => m.UserId.Equals(userId)).Select(m => new UserOrganizationDto
            {
                OrganizationId = m.OrganizationId,
                Administrator = m.Administrator,
                Leader = m.Leader,
            }).ToList();
            var addOrganizations = dtos.Except(existOrganizations).ToArray();
            var removeOrganizations = existOrganizations.Except(dtos).ToArray();

            if (!addOrganizations.Union(removeOrganizations).Any())
            {
                return OperationResult.Success();
            }

            try
            {
                foreach (var removeOrganization in removeOrganizations)
                {
                    //var organizationId = OrganizationRepository.QueryAsNoTracking(m => m.Id.Equals(removeOrganization.OrganizationId)).Select(m => m.Id).FirstOrDefault();
                    //if (Equals(organizationId, default(long)))
                    //{
                    //    throw new InvalidOperationException(I18N.T("组织机构 {0} 不存在", removeOrganization.OrganizationId));
                    //}
                    var result = await UserOrganizationRepository.DeleteBatchAsync(m => m.UserId.Equals(userId) && m.OrganizationId.Equals(removeOrganization.OrganizationId));
                    if (!result.Succeeded)
                    {
                        return result.ToOperationResult();
                    }
                }
                foreach (var addOrganization in addOrganizations)
                {
                    var organizationId = OrganizationRepository.QueryAsNoTracking(m => m.Id.Equals(addOrganization.OrganizationId)).Select(m => m.Id).FirstOrDefault();
                    if (Equals(organizationId, default(long)))
                    {
                        throw new InvalidOperationException(I18N.T("组织机构 {0} 不存在", addOrganization.OrganizationId));
                    }
                    UserOrganization userOrganization = new() { UserId = userId, OrganizationId = addOrganization.OrganizationId, Administrator = addOrganization.Administrator, Leader = addOrganization.Leader };
                    var result = await UserOrganizationRepository.InsertAsync(userOrganization);
                    if (!result.Succeeded)
                    {
                        return result.ToOperationResult();
                    }
                }

                //更新用户缓存使组织机构生效
                var eventData = new OnlineUserCacheRemoveEventData() { UserIds = new[] { user.Id.ToString() } };
                await EventBus.PublishAsync(eventData);
            }
            catch (InvalidOperationException ex)
            {
                return OperationResult.Error(ex.Message);
            }

            if (addOrganizations.Length > 0 && removeOrganizations.Length == 0)
            {
                return OperationResult.Success(I18N.T("用户 {0} 添加组织机构 {1} 成功", user.UserName, addOrganizations.Select(o => o.OrganizationId).ExpandAndToString()));
            }
            if (addOrganizations.Length == 0 && removeOrganizations.Length > 0)
            {
                return OperationResult.Success(I18N.T("用户 {0} 移除组织机构 {1} 成功", user.UserName, removeOrganizations.Select(o => o.OrganizationId).ExpandAndToString()));
            }
            return OperationResult.Success(I18N.T("用户 {0} 添加组织机构 {1} 、移除组织机构 {2} 成功。", user.UserName, addOrganizations.Select(o => o.OrganizationId).ExpandAndToString(), removeOrganizations.Select(o => o.OrganizationId).ExpandAndToString()));
        }
        #endregion
        #region "设置组织机构的用户"
        /// <summary>
        /// 设置组织机构的用户
        /// </summary>
        /// <param name="organizationId">组织机构编号</param>
        /// <param name="dtos">组织机构用户DTO集合</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> SetOrganizationUsers(long organizationId, params OrganizationUserDto[] dtos)
        {
            var org = OrganizationRepository.QueryAsNoTracking(m => m.Id.Equals(organizationId)).FirstOrDefault();
            if (org == null)
            {
                return OperationResult.Error(I18N.T("组织机构 {0} 不存在", organizationId));
            }
            var existUsers = UserOrganizations.Where(m => m.OrganizationId.Equals(organizationId)).Select(m => new OrganizationUserDto
            {
                UserId = m.UserId,
                Administrator = m.Administrator,
                Leader = m.Leader,
            }).ToList();
            var addUsers = dtos.Except(existUsers).ToArray();
            var removeUsers = existUsers.Except(dtos).ToArray();

            if (!addUsers.Union(removeUsers).Any())
            {
                return OperationResult.Success();
            }

            try
            {
                foreach (var removeUser in removeUsers)
                {
                    var result = await UserOrganizationRepository.DeleteBatchAsync(m => m.UserId.Equals(removeUser.UserId) && m.OrganizationId.Equals(organizationId));
                    if (!result.Succeeded)
                    {
                        return result.ToOperationResult();
                    }
                    User user = await UserManager.FindByIdAsync(removeUser.UserId.ToString());
                    if (user != null)
                    {
                        await UserManager.UpdateSecurityStampAsync(user);
                    }
                }
                foreach (var addUser in addUsers)
                {
                    User user = await UserManager.FindByIdAsync(addUser.UserId.ToString());
                    if (user == null)
                    {
                        return OperationResult.Error(I18N.T("用户 {0} 不存在", addUser.UserId));
                    }
                    UserOrganization userOrganization = new() { UserId = addUser.UserId, OrganizationId = organizationId, Administrator = addUser.Administrator, Leader = addUser.Leader };
                    var result = await UserOrganizationRepository.InsertAsync(userOrganization);
                    if (!result.Succeeded)
                    {
                        return result.ToOperationResult();
                    }
                    await UserManager.UpdateSecurityStampAsync(user);

                }

                var userIds = UserManager.Users.Where(m => addUsers.Union(removeUsers).Select(o => o.UserId).Contains(m.Id)).Select(m => m.Id.ToString()).ToArray();
                //更新用户缓存使组织机构生效
                var eventData = new OnlineUserCacheRemoveEventData() { UserIds = userIds };
                await EventBus.PublishAsync(eventData);
            }
            catch (InvalidOperationException ex)
            {
                return OperationResult.Error(ex.Message);
            }

            if (addUsers.Length > 0 && removeUsers.Length == 0)
            {
                return OperationResult.Success(I18N.T("组织机构 {0} 添加用户 {1} 成功", org.Name, addUsers.Select(o => o.UserId).ExpandAndToString()));
            }
            if (addUsers.Length == 0 && removeUsers.Length > 0)
            {
                return OperationResult.Success(I18N.T("组织机构 {0} 移除用户 {1} 成功", org.Name, removeUsers.Select(o => o.UserId).ExpandAndToString()));
            }
            return OperationResult.Success(I18N.T("组织机构 {0} 添加用户 {1} 、移除用户 {2} 成功。", org.Name, addUsers.Select(o => o.UserId).ExpandAndToString(), removeUsers.Select(o => o.UserId).ExpandAndToString()));
        }
        #endregion

        #endregion

    }
}
